package ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JComponent;

import util.ResourceManager;

public class PointCanvas extends JComponent {
	private static final int AXIS_OFFSET = 40;
	private boolean inputMode = false;

	private List<Point> points;
	private Point[] nearestPointPair = new Point[2];

	public PointCanvas(boolean input) {
		super();
		inputMode = input;
		this.setPreferredSize(new Dimension(2000, 2000));
		this.setBackground(Color.white);

		if (inputMode) {
			this.addMouseListener(new SetPointListener());
		}
	}

	protected void paintComponent(Graphics g) {
		drawAxis(g);
		drawPoints(g);
	}

	private void drawPoints(Graphics g) {
		g.setColor(Color.blue);
		List<Point> pts = this.getPoints();
		Iterator<Point> itr = pts.iterator();
		Point pt = null;
		while (itr.hasNext()) {
			pt = itr.next();
			int x = pt.x + AXIS_OFFSET;
			int y = pt.y + AXIS_OFFSET;
			g.drawLine(x - 1, y, x + 1, y);
			g.drawLine(x, y + 1, x, y - 1);
		}
		if (nearestPointPair[0] != null) {
			g.setColor(Color.red);
			int x1 = nearestPointPair[0].x + AXIS_OFFSET;
			int y1 = nearestPointPair[0].y + AXIS_OFFSET;
			g.drawLine(x1 - 1, y1, x1 + 1, y1);
			g.drawLine(x1, y1 + 1, x1, y1 - 1);
			int x2 = nearestPointPair[1].x + AXIS_OFFSET;
			int y2 = nearestPointPair[1].y + AXIS_OFFSET;
			g.drawLine(x2 - 1, y2, x2 + 1, y2);
			g.drawLine(x2, y2 + 1, x2, y2 - 1);
			g.drawLine(x1, y1, x2, y2);
		}
	}

	private void drawAxis(Graphics g) {
		int h = this.getHeight() - AXIS_OFFSET;
		int w = this.getWidth() - AXIS_OFFSET;
		g.drawLine(AXIS_OFFSET, AXIS_OFFSET, this.getWidth(), AXIS_OFFSET);
		g.drawLine(AXIS_OFFSET, AXIS_OFFSET, AXIS_OFFSET, this.getHeight());

		g.drawString("0", 20, 30);
		for (int i = 100; i < h; i += 100) {
			g.drawLine(AXIS_OFFSET - 5, AXIS_OFFSET + i, AXIS_OFFSET,
					AXIS_OFFSET + i);
			g.drawString("" + i, AXIS_OFFSET - 30, AXIS_OFFSET + i);
		}

		for (int i = 100; i < w; i += 100) {

			g.drawLine(AXIS_OFFSET + i, AXIS_OFFSET - 5, AXIS_OFFSET + i,
					AXIS_OFFSET);
			g.drawString("" + i, AXIS_OFFSET + i, AXIS_OFFSET - 20);
		}

	}

	public List<Point> getPoints() {
		if (points == null) {
			points = new ArrayList<Point>();
		}
		return points;
	}

	public void setPoints(List<Point> points) {
		this.points = points;
		this.setPreferredSize(new Dimension(ResourceManager
				.calcCanvasRange(points.size()), ResourceManager
				.calcCanvasRange(points.size())));
	}

	public void setNearestPointPair(Point[] pts) {
		if (pts != null && pts.length == 2 && pts[0] != null && pts[1] != null) {
			this.nearestPointPair[0] = pts[0];
			this.nearestPointPair[1] = pts[1];
		}
	}

	class SetPointListener extends MouseAdapter {
		public void mousePressed(MouseEvent arg0) {
			int x = arg0.getX() - AXIS_OFFSET;
			int y = arg0.getY() - AXIS_OFFSET;

			if (x >= 0 && y >= 0) {
				Point p = new Point(x, y);
				if (!getPoints().contains(p)) {
					getPoints().add(p);
				}
				repaint();
			}
		}
	}

}
